﻿#region << 文 件 说 明 >>

/*----------------------------------------------------------------
// 文件名称：BillListBaseVM
// 创 建 者：杨程
// 创建时间：2022/2/9 19:48:54
// 文件版本：V1.0.0
// ===============================================================
// 功能描述：
//
//
//----------------------------------------------------------------*/

#endregion

namespace Vampirewal.Core.SimpleMVVM;

/// <summary>
/// 列表查询VM基类
/// </summary>
/// <typeparam name="TBillEntity">弹窗实体模型</typeparam>
/// <typeparam name="TSearchEntity">列表模型</typeparam>
public abstract partial class BillListBaseVM<TBillEntity, TSearchEntity> : ViewModelBase
    where TBillEntity : BillBaseModel, new()
     where TSearchEntity : ObservableObject, new()
{
    /// <summary>
    /// 弹窗服务
    /// </summary>
    protected IVampirewalCoreDialogMessage Dialog { get; set; }

    /// <summary>
    /// 实体模型数据库
    /// </summary>
    protected SqlSugarRepository<TBillEntity> RepBill { get; set; }

    /// <summary>
    /// 列表模型数据库
    /// </summary>
    protected SqlSugarRepository<TSearchEntity> RepSearch { get; set; }

    /// <summary>
    /// 构造函数
    /// </summary>
    public BillListBaseVM()
    {
        EntityList ??= new ObservableCollection<TBillEntity>();
        SetDialogWindowSetting(null);
        Limit = VampirewalCoreContext.GetInstance().GetService<IConfigContainer< PagingOptions>>().Value.Limit;
        InitVM();
    }

    /// <summary>
    /// 分页设置
    /// </summary>
    public PagingOptions PageSetting { get; set; }

    /// <summary>
    /// 构造函数
    /// </summary>
    public BillListBaseVM(IVampirewalCoreDialogMessage dialog, SqlSugarRepository<TBillEntity> repBill, SqlSugarRepository<TSearchEntity> repSearch) : base()
    {
        Dialog = dialog;
        RepBill = repBill;
        RepSearch = repSearch;
        //构造函数
        EntityList ??= new ObservableCollection<TBillEntity>();
        Limit = VampirewalCoreContext.GetInstance().GetService<IConfigContainer<PagingOptions>>().Value.Limit;

        SetDialogWindowSetting(null);
        InitVM();
    }

    #region 属性

    /// <summary>
    /// 界面上显示的预制按钮
    /// </summary>
    [ObservableProperty]
    private ListViewButton listButton;

    /// <summary>
    /// 列表
    /// </summary>
    public ObservableCollection<TBillEntity> EntityList { get; set; }

    #region 分页相关

    /// <summary>
    /// 当前页
    /// </summary>
    [ObservableProperty]
    private int page = 1;

    /// <summary>
    /// 每页数
    /// </summary>
    [ObservableProperty]
    private int limit = 20;

    /// <summary>
    /// 记录数
    /// </summary>
    [ObservableProperty]
    private long count;

    /// <summary>
    /// 分页数
    /// </summary>
    [ObservableProperty]
    private int pageCount = 0;

    /// <summary>
    /// 数据总条数
    /// </summary>
    [ObservableProperty]
    private int totalCount;

    #endregion

    #region 弹窗相关

    /// <summary>
    /// 弹窗窗体属性设置
    /// </summary>
    protected DialogWindowSetting DialogSetting { get; private set; }

    /// <summary>
    /// <para>★设置弹窗窗体的基本属性★</para>
    /// <para>无需设置：UiView和PassData（UiView通过SetView()取值，PassData需要传递当前ListVM的选择项）</para>
    /// </summary>
    /// <param name="setting"></param>
    protected void SetDialogWindowSetting(DialogWindowSetting setting)
    {
        DialogSetting = setting;

        if (setting == null)
        {
            DialogSetting = new DialogWindowSetting()
            {
                WindowWidth = 1366,
                WindowHeight = 768,
                IsShowMaxButton = true,
                IsShowMinButton = true,
                IsOpenWindowSize = false,
                TitleFontSize = 15,
                CloseDialogWindowCallBackCommand = new RelayCommand<object>(ExecuteBeforeCloseDialogWindow)
            };
        }
    }

    #endregion

    #endregion

    #region 公共方法

    /// <summary>
    /// 初始化ViewModel
    /// </summary>
    protected abstract void InitVM();

    /// <summary>
    /// 重新初始化ViewModel(需保留Base)
    /// </summary>
    protected virtual void ReInitVM()
    {
        InitVM();
    }

    ///// <summary>
    ///// <para>★调用之后给<paramref name="EntityList"/>进行赋值★</para>
    ///// <para>1、如果使用<paramref name="SqlSugar"/>进行取值的话，直接赋值<paramref name="Queryable"/>即可</para>
    ///// <para>2、如果使用其他方式给<paramref name="EntityList"/>赋值，这个方法可重写，也可以自己写方法给<paramref name="EntityList"/>赋值</para>
    ///// </summary>
    ///// <param name="IsUseGetSearchQuery">是否使用GetSearchQuery()进行查询,如果为false的话，需要对<paramref name="Queryable"/>进行赋值</param>
    ///// <param name="UsePageQuery">是否使用分页查询，默认<paramref name="False"/></param>
    //protected virtual void GetList(bool IsUseGetSearchQuery,bool UsePageQuery=false)
    //{
    //    //EntityList.Clear();

    //    //var baseQuery = IsUseGetSearchQuery? GetSearchQuery(): Queryable;

    //    //List<TBillEntity> list = new List<TBillEntity>();

    //    //if (UsePageQuery)
    //    //{
    //    //    int total = 0;
    //    //    int totalPage = 0;

    //    //    list = RepBill.AsQueryable(baseQuery).ToPageList(Page, Limit, ref total, ref totalPage);

    //    //    PageCount = totalPage;
    //    //    TotalCount = total;
    //    //}
    //    //else
    //    //{
    //    //    list = RepBill.AsQueryable(baseQuery).ToList();
    //    //}

    //    //foreach (var item in list)
    //    //{
    //    //    EntityList.Add(item);
    //    //}
    //}

    /// <summary>
    /// <para>★调用之后给<paramref name="EntityList"/>进行赋值★</para>
    /// <para>如果使用其他方式给<paramref name="EntityList"/>赋值，这个方法可重写，也可以自己写方法给<paramref name="EntityList"/>赋值</para>
    /// </summary>
    /// <param name="expression">查询条件</param>
    /// <param name="order">排序条件</param>
    /// <param name="type">排序类型</param>
    /// <param name="UsePage">是否使用分页</param>
    protected virtual void GetPageList(Expression<Func<TBillEntity, bool>> expression, Expression<Func<TBillEntity, object>> order, OrderByType type = OrderByType.Asc, bool UsePage = true)
    {
        EntityList.Clear();

        List<TBillEntity> list;

        if (UsePage)
        {
            int total = 0;
            int totalPage = 0;
            list = RepBill.QueryableToPage(expression, order, type, Page, limit, ref total, ref totalPage);

            PageCount = totalPage;
            TotalCount = total;
        }
        else
        {
            list = RepBill.Entities.OrderByIF(order != null, order, type).Where(expression).ToList();
        }

        foreach (var item in list)
        {
            EntityList.Add(item);
        }
    }

    /// <summary>
    /// 获取需要弹窗的窗体
    /// </summary>
    /// <returns></returns>
    protected abstract IUcViewBase SetView();

    #endregion



    #region 命令

    /// <summary>
    /// 搜索命令执行方法
    /// </summary>
    /// <param name="SearchText">模糊搜索文本</param>
    [RelayCommand]
    protected virtual void ExecuteSearch(string SearchText)
    {
    }

    /// <summary>
    /// 高级搜索命令执行方法
    /// </summary>
    /// <param name="s">高级搜索对应模型</param>
    [RelayCommand]
    protected virtual void ExecuteSeniorSearch(object s)
    {
    }

    /// <summary>
    /// 点击之后会弹出窗体方法
    /// </summary>
    /// <param name="PassEntity">传递过去的参数</param>
    [RelayCommand]
    protected virtual void ExecuteShowDialogWindow(object PassEntity)
    {
        try
        {
            var DialogWindow = SetView();

            if (DialogWindow != null)
            {
                //var vm = DialogWindow.DataContext as BillVM<TBillEntity>;

                if (DialogWindow.DataContext is not ViewModelBase vm)
                {
                    //throw new Exception("对应弹窗窗体的ViewModel不是BillVM！");
                    throw new Exception("对应弹窗窗体的ViewModel不是ViewModelBase！");
                }

                DialogSetting.UcView = DialogWindow;
                DialogSetting.PassData = PassEntity;

                Dialog.OpenDialogWindow(DialogSetting);
            }
            else
            {
                throw new Exception("未找到对应窗体！");
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    /// <summary>
    /// 弹窗关闭窗口的时候，先执行这个方法，然后关闭
    /// </summary>
    [RelayCommand]
    public virtual void ExecuteBeforeCloseDialogWindow(object obj)
    {
    }

    /// <summary>
    /// 执行导出Excel方法
    /// </summary>
    /// <param name="searches"></param>
    [RelayCommand]
    public virtual void ExecuteExportExcel(List<TSearchEntity> searches)
    {
    }

    #endregion
}